package com.graphite.client;

import com.alibaba.fastjson.JSON;
import com.graphite.http.FetchGraphite;
import com.graphite.http.HttpClientPool;
import com.graphite.model.BaseRequest;
import com.graphite.model.BaseResponse;
import com.graphite.model.GraphiteMetric;
import com.graphite.task.FetchGraphiteDataTaskExector;
import com.graphite.util.InvokeUtil;
import com.graphite.util.MetricUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeoutException;


/**
 * @param <K>
 * @param <V>
 * @projectName: collect-service
 * @packageName: com.graphite.client
 * @className: com.graphite.client-> GraphiteClient
 * @createDate: 2021-05-31 17:17
 * @author: ZhangSheng
 * @version: 1.0
 * @description: GraphiteClient 客户端操作类
 */
public class GraphiteNettyClient<K extends BaseRequest, V extends BaseResponse> implements FetchGraphite<K, V> {

    private static Logger logger = LoggerFactory.getLogger(GraphiteNettyClient.class);

    private final ExecutorService executor = Executors.newSingleThreadExecutor();

    private final FetchGraphiteDataTaskExector taskExector = new FetchGraphiteDataTaskExector();

    public GraphiteNettyClient() {
    }


    public boolean sendData(String host, int port, List<GraphiteMetric> graphiteMetrics) throws InterruptedException,
            ExecutionException, TimeoutException {
        boolean isSend = true;
        if (StringUtils.isBlank(host)) {
            isSend = false;
            logger.error("Graphite host is null,you should set a host.");
        } else if (null != graphiteMetrics && 0 != graphiteMetrics.size()) {
            return this.taskExector.submit(host, port, graphiteMetrics);
        } else {
            isSend = false;
            logger.error("GraphiteClient#sendData No data to send to graphite.");
        }
        return isSend;
    }

    public V fetchData(K k) throws IOException, URISyntaxException {
        List<NameValuePair> pairs = new ArrayList();
        if (null == k) {
            return null;
        } else {
            Field[] fields = InvokeUtil.getFields(k);
            if (fields != null) {
                Field[] var4 = fields;
                int var5 = fields.length;
                for (int var6 = 0; var6 < var5; ++var6) {
                    Field field = var4[var6];
                    Object fieldValue = InvokeUtil.getFieldValueByName(field, k);
                    if (null != fieldValue && !field.getName().equals("serialVersionUID")) {
                        pairs.add(new BasicNameValuePair(field.getName(), fieldValue.toString()));
                    }
                }
            }
            CloseableHttpResponse response = null;
            CloseableHttpClient httpClient = null;
            V v = null;

            String result;
            try {
                long startTime = System.currentTimeMillis();
                httpClient = HttpClientPool.getHttpClient();
                URIBuilder builder = new URIBuilder(k.getEndpoint());
                builder.setParameters(pairs);
                HttpGet httpGet = new HttpGet(builder.build());
                logger.info("请求的URI:{}", httpGet.getURI());
                response = httpClient.execute(httpGet);
                long endTime = System.currentTimeMillis();
                logger.info("FetchGraphiteData请求Graphite单条数据耗时（毫秒）：" + (endTime - startTime));
                HttpEntity entity = null;
                if (response != null && response.getStatusLine().getStatusCode() == 200) {
                    entity = response.getEntity();
                    result = EntityUtils.toString(entity, "UTF-8");
                    result = result.substring(1, result.length() - 1);
                    v = (V) JSON.parseObject(result, k.getConvertClass());
                    if (v != null) {
                        v.setUuid(k.getUuid());
                        if (StringUtils.isBlank(v.getUuid())) {
                            v.setUuid(MetricUtil.getResourceId(v.getTarget()));
                        }
                    }
                    return v;
                }
            } finally {
                if (response != null) {
                    try {
                        response.close();
                    } catch (Exception var31) {
                        logger.error("GraphiteClient#fetchData Exception:", var31);
                    }
                }
            }
            return v;
        }
    }
}
